/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author pipo
 */
package mainGame;


import java.util.ArrayList;
import java.util.List;
import java.util.Random;


//Electric : Most Damage, Least Defense
//Fire: Good Damage, Poor Defense
//Water: Medium Damage, Medium Defense
//Earth: Least Damage , Most Defense 


public class Pokemon{
    
    protected List<Attack> attackList;
    protected int rawPower, rawDefense, hitPoints, level, type , maxHitPoints;
    protected int experience , nextLevel;
    protected String name;
    
    public Pokemon(int rawPower, int rawDefense, int hitPoints, int type, int level , String name )
    {
        this.experience = 0;
        this.nextLevel = 10;
        this.rawPower = rawPower;
        this.rawDefense = rawDefense;
        this.hitPoints = hitPoints; 
        this.maxHitPoints = hitPoints;
        this.level = level;
        this.type = type;
        this.name = name;
        this.attackList = new ArrayList<Attack>();
        this.initializeAttacks();
        
    }

    public void initializeAttacks()
    {
        String attack1 , attack2 , attack3;
        String descr1 , descr2 , descr3;
        descr1 = "Low Damage , Low Risk Attack; ( Damage Multiplier = 1 ) ";
        descr2 = "Medium Damage , Medium Risk Attack; (Damage Multiplier = 0.70 - 1.40)";
        descr3 = "High Damage , High Risk Attack; (Damage Multiplier = 0.55 - 1.75 ) "; 
        
        if(this.type == 1)
        {
            attack1 = "Electric Bolt";
            attack2 = "Shock Pulse";
            attack3 = "Thunder";
        }
        
        else if(this.type == 2)
        {
            attack1 = "Fire Bolt";
            attack2 = "Flame Breath";
            attack3 = "Meteor Shower";
            
        }
        
        else if(this.type == 3)
        {
            
            attack1 = "Stone Strike";
            attack2 = "Ground Shake";
            attack3 = "Earthquake";
        }
        
        else
        {
            attack1 = "Water Splash";
            attack2 = "Water Cannon";
            attack3 = "Tsunami";
        }
        
        Attack a1 = new Attack(attack1 , descr1);
        Attack a2 = new Attack(attack2 , descr2);
        Attack a3 = new Attack(attack3 , descr3);
        
        this.addAttack(a1);
        this.addAttack(a2);
        this.addAttack(a3);
        
        
    }
   
    public int calculateRawDamage(Pokemon enemy)
    {
        //type = 1 : Electric , type = 2: Fire , type = 3: Earth , type = 4: Water
        //Electric type good against Water, bad against Earth and Electric type; equal with fire
        //Fire type good against Earth, bad against water and fire; equal with electric
        //Water type good against Fire and bad against electric and water; equal with earth
        //Earth type good against electric and bad against Fire and Earth; equal with Water

        
        Random generator = new Random();
        
        float damageCoeff = (float) generator.nextFloat()/5;
        damageCoeff = (float) (damageCoeff + 0.80);
        
        float badCoeff = (float) (damageCoeff * 0.75);
        float goodCoeff = (float) (damageCoeff * 1.25) ;
        float equalCoeff = damageCoeff * 1;
        
        
        if(this.type == 1)
        {
            if(enemy.getType() == 1)
                return (int) (this.rawPower * badCoeff) ;
            else if(enemy.getType() == 2)
                return (int) (this.rawPower * equalCoeff);
            else if(enemy.getType() == 3)
                return (int) (this.rawPower * badCoeff);
            else if(enemy.getType() == 4)
                return (int) (this.rawPower * goodCoeff);
        }
        
        
        else if(this.type == 2)
        {
            if(enemy.getType() == 1)
                return (int) (this.rawPower * equalCoeff);
            else if(enemy.getType() == 2)
                return (int) (this.rawPower * badCoeff);
            else if(enemy.getType() == 3)
                return (int) (this.rawPower * goodCoeff);
            else if(enemy.getType() == 4)
                return (int) (this.rawPower * badCoeff);
        }
        
        else if(this.type == 3)
        {
            if(enemy.getType() == 1)
                return (int) (this.rawPower * goodCoeff);
            else if(enemy.getType() == 2)
                return (int) (this.rawPower * badCoeff);
            else if(enemy.getType() == 3)
                return (int) (this.rawPower * badCoeff);
            else if(enemy.getType() == 4)
                return (int) (this.rawPower * equalCoeff);
        }
        
        
        else if(this.type == 4)
        {
            if(enemy.getType() == 1)
                return (int) (this.rawPower * badCoeff);
            else if(enemy.getType() == 2)
                return (int) (this.rawPower * goodCoeff);
            else if(enemy.getType() == 3)
                return (int) (this.rawPower * equalCoeff);
            else if(enemy.getType() == 4)
                return (int) (this.rawPower * badCoeff);
        }
        
        
        return this.rawPower;
      
    }
    
    public int calculateDamage(Pokemon enemy, int choosenAttack)
    {
                
        //attack.power = 0 -> low damage, no risk coeff = 1
        //attack.power = 1 -> medium damage , medium risk coeff  = 0.70 - 1.40
        //attack.power = 2 -> high damage, high risk coeff = (0.55 - 1.75)
        
        float attackCoeff;
        Random generator = new Random();
        
        
       if(choosenAttack == 1)
        {
            attackCoeff = (float) generator.nextFloat() * 70;
            attackCoeff /= 100;
            attackCoeff = (float) (attackCoeff + 0.70);
        }
        
        else if(choosenAttack == 2)
        {
            attackCoeff = (float) (generator.nextFloat() * 120);
            attackCoeff /= 100;
            attackCoeff = (float) (attackCoeff + 0.55);
        }
        
        else 
            attackCoeff = 1;
        
        return (int) (attackCoeff * calculateRawDamage(enemy));
        
    }
    
    public int calculateDefense(Pokemon enemy)
    {
        
        //Earth is strong against all
        //Electric is weak against all
        //Water is weak against Electric and strong against rest
        //Fire is weak against Water, Electric and strong against rest
        
        Random generator = new Random();
        float defenseCoeff = (float) generator.nextFloat()/5;
        defenseCoeff = (float) (defenseCoeff + 0.80);
        
        float badCoeff = (float) (defenseCoeff * 0.75);
        float goodCoeff = (float) (defenseCoeff * 1.5) ;

        if(this.type == 1)
        {
            
            return (int) (this.rawDefense * badCoeff);
            
        }
        
        else if(this.type == 2)
        {
            
            if(enemy.getType() == 1 || enemy.getType() == 4)
                return (int) (this.rawDefense * badCoeff);
            else
                return (int) (this.rawDefense * goodCoeff);
            
        }
        
        else if(this.type == 3)
        {
            
            return (int) (this.rawDefense * goodCoeff);
            
        }
        
        else if(this.type == 4)
        {
            if(enemy.getType() == 1)
                return (int) (this.rawDefense * badCoeff);
            else
                return (int) (this.rawDefense * goodCoeff);
           
        }
        
    return this.rawDefense;    
        
    }
    

    public int calculateOverallDamage(Pokemon Enemy, int choosenAttack)
    {
        
        int damage = this.calculateDamage(Enemy , choosenAttack);
        int defense = this.calculateDefense(Enemy);
        int overallDamage = damage - defense;
        
        if(overallDamage > 0 )
            return overallDamage;
        else
            return 0;
        
    }
    
    
    public int getType()
    {
        return this.type;
    }
    
    
    
    public void reduceHitPoints(int damage)
    {
        
        int newHP = this.hitPoints - damage;
        if(newHP > 0)
            this.hitPoints = newHP;
        else
            this.hitPoints = 0;
    
    }
    
    public boolean isPokemonDead()
    {
        
        return this.hitPoints <= 0;
    }
    
    public int expAmountWhenKilled()
    {
        return (int) (this.level* 3) + 7 ;
        
    }
    
    public void updateAttributes(int times)
    {
        for(int i = 0 ; i < times ;  i++)
        {
            this.level++;
            if(this.experience > 0 ) this.experience = this.experience - this.nextLevel;
            else this.experience = 0;
            this.nextLevel = (int) (10 * (1 + (this.level/3.0)));
            this.rawDefense = (int) (this.rawDefense * 1.1);
            this.rawPower = (int) (this.rawPower * 1.1);
            this.maxHitPoints = (int) (this.maxHitPoints * 1.1);
            this.hitPoints = this.maxHitPoints;
        }
    }
    
    public String getName()
    {
        return this.name;
        
    }
    
    public void addAttack(Attack a)
    {
        this.attackList.add(a);   
    }
    
    public String getProperties()
    {
        
        String properties;
        String typ; 
        if(this.getType() == 1) typ = "Electric";
        else if(this.getType() == 2) typ = "Fire";
        else if(this.getType() == 3) typ = "Earth";
        else typ = "Water";
        properties = "Name: " + this.getName() + "  |  Type: " + typ +  "  |  Level: " + this.level + "  |  Raw Damage: " + this.rawPower + "  |  Raw Defense: " + this.rawDefense 
                + "  |  Hit Points: " + this.hitPoints + " / " + this.maxHitPoints + "  |  Experience: " +this.experience + " / " +this.nextLevel;
        return properties;
        
    }
    
    public String getAttackName(int index)
    {
        return this.attackList.get(index).getName();
        
    }
    
    public String getAttackDescr(int index)
    {
        
        return this.attackList.get(index).getDescr();
        
    }
    
    public void refresh(int divider)
    {
        int newHealth = this.hitPoints + (int) (this.maxHitPoints / divider);
        if(newHealth > this.maxHitPoints)
            this.hitPoints = this.maxHitPoints;
        else
            this.hitPoints = newHealth;
    }
    
    public String getStringExperience()
    {
        return "Experience: " + this.experience + "  /  "  + this.nextLevel;
        
    }
    
    public void addExperience(int amount)
    {
        this.experience = this.experience + amount;
        
    }
    
    public int getExperience()
    {
        return this.experience;
    }
    
    public int getNextLevelExperience()
    {
        
        return this.nextLevel;
    }
    
    public void reduceExperience()
    {
        
        this.experience = (int) (this.experience / 2 );
        
    }
    
    public int getPercent()
    {
        
        int percent;
        percent = (int) ( (double) ((this.hitPoints * 1.0) / this.maxHitPoints) * 100 );
        return percent;
    }
    
    public int calculateScore()
    {
        return this.level*10;
    }
    
    public int getLevel()
    {
        return this.level;
        
    }
    

    
    public int getRawPower()
    {
        return this.rawPower;
    }
    
    public int getRawDefense()
    {
        return this.rawDefense;
    }
    
    public int getHitPoints()
    {
        return this.hitPoints;
    }
    
    public int getMaxHitPoints()
    {
        return this.maxHitPoints;
    }
    
    public void setHitPoints(int hitPoints)
    {
        this.hitPoints  = hitPoints;
    }
    
    public void setExperience(int experience)
    {
        this.experience = experience;
    }
    
    public void setNextLevelExperience(int nextExp)
    {
        this.nextLevel = nextExp;
    }
    
}
